package com.lineage.server.timecontroller.pc;

import com.lineage.server.model.Instance.L1MonsterInstance;
import com.lineage.server.model.Instance.L1PcInstance;
import com.lineage.server.model.L1Character;
import com.lineage.server.model.L1Object;
import com.lineage.server.serverpackets.S_DoActionGFX;
import com.lineage.server.serverpackets.ServerBasePacket;
import com.lineage.server.thread.PcOtherThreadPool;
import com.lineage.server.types.Point;
import com.lineage.server.world.World;
import java.util.Collection;
import java.util.Iterator;
import java.util.Random;
import java.util.TimerTask;
import java.util.concurrent.ScheduledFuture;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class PcGhostTimer extends TimerTask {
  private static final Log _log = LogFactory.getLog(PcGhostTimer.class);
  
  private ScheduledFuture<?> _timer;
  
  protected static final Random _random = new Random();
  
  public void start() {
    int timeMillis = 1100;
    this._timer = PcOtherThreadPool.get().scheduleAtFixedRate(this, 1100L, 1100L);
  }
  
  public void run() {
    try {
      Collection<?> all = World.get().getAllPlayers();
      if (all.isEmpty())
        return; 
      Iterator<?> iter = all.iterator();
      while (iter.hasNext()) {
        L1PcInstance tgpc = (L1PcInstance)iter.next();
        if (!tgpc.isDead()) {
          if (tgpc.hasSkillEffect(7007)) {
            wind_dmg(tgpc);
          } else if (tgpc.hasSkillEffect(7008)) {
            earth_dmg(tgpc);
          } 
          if (!tgpc.isGhost())
            continue; 
          int time = tgpc.get_ghostTime();
          time--;
          check(tgpc, Integer.valueOf(time));
          Thread.sleep(1L);
        } 
      } 
    } catch (Exception e) {
      _log.error("PC 鬼魂模式处理时间轴异常重启", e);
      PcOtherThreadPool.get().cancel(this._timer, false);
      PcGhostTimer pcghostTimer = new PcGhostTimer();
      pcghostTimer.start();
    } 
  }
  
  private void earth_dmg(L1PcInstance pc) {
    try {
      int damage = c3_power_dmg(pc, 4);
      Iterator<L1Object> iterator = World.get().getVisibleObjects((L1Object)pc, 1).iterator();
      while (iterator.hasNext()) {
        L1Object tgobj = iterator.next();
        if (tgobj instanceof L1PcInstance) {
          L1PcInstance tgpc = (L1PcInstance)tgobj;
          if (tgpc.isDead() || (tgpc.getClanid() == pc.getClanid() && tgpc.getClanid() != 0) || 
            tgpc.getMap().isSafetyZone((Point)tgpc.getLocation()))
            continue; 
          int resist = tgpc.getEarth();
          if (resist > 0) {
            damage = c3_power_dmg_down(damage, Math.min(100, resist));
          } else if (resist < 0) {
            damage = c3_power_dmg_up(damage, Math.min(0, resist));
          } 
          tgpc.receiveDamage((L1Character)pc, damage, false, true);
          tgpc.sendPacketsX8((ServerBasePacket)new S_DoActionGFX(tgpc.getId(), 2));
          continue;
        } 
        if (!(tgobj instanceof L1MonsterInstance))
          continue; 
        L1MonsterInstance tgmob = (L1MonsterInstance)tgobj;
        if (tgmob.isDead())
          continue; 
        tgmob.receiveDamage((L1Character)pc, damage, 1);
        tgmob.broadcastPacketX8((ServerBasePacket)new S_DoActionGFX(tgmob.getId(), 2));
      } 
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
  
  private void wind_dmg(L1PcInstance pc) {
    try {
      int damage = c3_power_dmg(pc, 3);
      Iterator<L1Object> iterator = World.get().getVisibleObjects((L1Object)pc, 1).iterator();
      while (iterator.hasNext()) {
        L1Object tgobj = iterator.next();
        if (tgobj instanceof L1PcInstance) {
          L1PcInstance tgpc = (L1PcInstance)tgobj;
          if (tgpc.isDead() || (tgpc.getClanid() == pc.getClanid() && tgpc.getClanid() != 0) || 
            tgpc.getMap().isSafetyZone((Point)tgpc.getLocation()))
            continue; 
          int resist = tgpc.getWind();
          if (resist > 0) {
            damage = c3_power_dmg_down(damage, Math.min(100, resist));
          } else if (resist < 0) {
            damage = c3_power_dmg_up(damage, Math.min(0, resist));
          } 
          tgpc.receiveDamage((L1Character)pc, damage, false, true);
          tgpc.sendPacketsX8((ServerBasePacket)new S_DoActionGFX(tgpc.getId(), 2));
          continue;
        } 
        if (!(tgobj instanceof L1MonsterInstance))
          continue; 
        L1MonsterInstance tgmob = (L1MonsterInstance)tgobj;
        if (tgmob.isDead())
          continue; 
        tgmob.receiveDamage((L1Character)pc, damage, 8);
        tgmob.broadcastPacketX8((ServerBasePacket)new S_DoActionGFX(tgmob.getId(), 2));
      } 
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
  
  private int c3_power_dmg_down(int damage, int resist) {
    int r = 100 - resist;
    int dmg = damage * r / 100;
    return Math.max(5, dmg);
  }
  
  private int c3_power_dmg_up(int damage, int resist) {
    int dmg = damage - damage * resist / 100;
    return Math.abs(dmg);
  }
  
  private int c3_power_dmg(L1PcInstance pc, int type) {
    int damage = 0;
    int level = pc.getLevel();
    switch (type) {
      case 3:
        if (level >= 50 && level < 70) {
          damage = random_dmg(15, 35);
          break;
        } 
        if (level >= 70 && level < 90) {
          damage = random_dmg(20, 40);
          break;
        } 
        if (level >= 90 && level < 110) {
          damage = random_dmg(25, 45);
          break;
        } 
        if (level >= 110 && level < 130) {
          damage = random_dmg(30, 50);
          break;
        } 
        if (level >= 130 && level < 150) {
          damage = random_dmg(35, 55);
          break;
        } 
        if (level >= 150 && level < 175) {
          damage = random_dmg(40, 60);
          break;
        } 
        if (level >= 175 && level < 190) {
          damage = random_dmg(45, 65);
          break;
        } 
        if (level >= 190 && level < 200) {
          damage = random_dmg(50, 70);
          break;
        } 
        damage = random_dmg(60, 100);
        break;
      case 4:
        if (level >= 50 && level < 70) {
          damage = random_dmg(15, 35);
          break;
        } 
        if (level >= 70 && level < 90) {
          damage = random_dmg(20, 40);
          break;
        } 
        if (level >= 90 && level < 110) {
          damage = random_dmg(25, 45);
          break;
        } 
        if (level >= 110 && level < 130) {
          damage = random_dmg(30, 50);
          break;
        } 
        if (level >= 130 && level < 150) {
          damage = random_dmg(35, 55);
          break;
        } 
        if (level >= 150 && level < 175) {
          damage = random_dmg(40, 60);
          break;
        } 
        if (level >= 175 && level < 190) {
          damage = random_dmg(45, 65);
          break;
        } 
        if (level >= 190 && level < 200) {
          damage = random_dmg(50, 70);
          break;
        } 
        damage = random_dmg(60, 100);
        break;
    } 
    return damage;
  }
  
  private int random_dmg(int i, int j) {
    return _random.nextInt(j - i) + i;
  }
  
  private static void check(L1PcInstance tgpc, Integer time) {
    if (time.intValue() > 0) {
      if (tgpc.isDead()) {
        tgpc.set_ghostTime(-1);
      } else {
        tgpc.set_ghostTime(time.intValue());
      } 
    } else {
      tgpc.set_ghostTime(-1);
      if (tgpc.getNetConnection() != null)
        outPc(tgpc); 
    } 
  }
  
  private static void outPc(L1PcInstance tgpc) {
    try {
      if (tgpc != null)
        tgpc.makeReadyEndGhost(); 
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
}
